package gui;


import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.print.PrinterException;
import java.awt.print.PrinterJob;
import java.util.ArrayList;
import java.util.HashMap;

import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.ScrollPaneConstants;

import app.Cookbook;
import app.Ingredient;
import app.Measurement;
import app.Recipe;
import net.miginfocom.swing.MigLayout;





/********************************************************
 *
 *  Project :  TeamProject
 *  Package :  gui
 *  File    :  RecipePanel.java
 *  Name    :  Tyler Daines
 *  Date    :  Nov 4, 2013
 *
 ********************************************************/
public class RecipePanel extends JPanel implements ActionListener, MouseListener
{
	private JLabel nameLabel, ingredientsLabel, instructionsLabel, numServingsLabel, calorieLabel, pictureLabel;
	private ImagePanel picturePanel;
	private JScrollPane ingredientScroll, instructionScroll;
	private JTextField nameField, numServingsField, caloriesField;
	private JTextArea instructionsArea;
	private JButton plusIngField, minusIngField, saveButton, cancelButton, printButton, deleteButton;
	private JComboBox<String> categoryCombo;
	private JCheckBox favoriteCheckBox;
	private ArrayList<Ingredient> ingredients;

	private Cookbook cookbook;
	private IngredientPanel ingredientPanel;
	private Recipe recipe;
	private JFileChooser fileChooser;
	
	
	private static int BUTTON_WIDTH = 115, BUTTON_HEIGHT = 25;
	
	/********************************************************
	 * Name       : RecipePanel
	 * Purpose    : New Recipe Constructor
	 * Parameters : 
	 ********************************************************/
	public RecipePanel()
	{
		
		setLayout(new MigLayout());
		
		cookbook = new Cookbook();		
		recipe = new Recipe();
		ingredients = recipe.getIngredients();
		fileChooser = new JFileChooser();
		initLabels();		
		initTextFields(recipe.getName(), recipe.getServingSize(), recipe.getCalories());
		initTextArea(recipe.getDirections());
		initButtons();
		initBoxs(0,false);
		initPanel();
		initImage(recipe.getPicture());
		addComponents();

		
	}

	/********************************************************
	 * Name       : RecipePanel
	 * Purpose    : Constructor for recipe from DB
	 * Parameters : Recipe recipe
	 ********************************************************/
	public RecipePanel(Recipe recipe)
	{
		
		setLayout(new MigLayout());
		cookbook = new Cookbook();
		this.recipe = recipe;
		this.ingredients = recipe.getIngredients();	
		fileChooser = new JFileChooser();
		initLabels();		
		initTextFields(recipe.getName(), recipe.getServingSize(), recipe.getCalories());
		initTextArea(recipe.getDirections());
		initButtons();
		initBoxs(recipe.getCategoryID(), recipe.isFavorite());
		initPanel();
		
		initImage(recipe.getPicture());

		addComponents();

		
		
		
	}

	/********************************************************
	* Name       : initLabels
	* Purpose    : Initialize labels
	* Returns    : void
	********************************************************/
	private void initLabels()
	{
		nameLabel = new JLabel("Recipe Name:");
		ingredientsLabel = new JLabel("Ingredients:");
		instructionsLabel = new JLabel("Directions:");
		numServingsLabel = new JLabel("# of Servings:");
		calorieLabel = new JLabel("Calories:");
		pictureLabel = new JLabel("Double-Click To Update Photo");
	}

	/********************************************************
	* Name       : initTextFields
	* Purpose    : Initialize the text fields.
	* Parameters : String name, String servingSize, String calories
	* Returns    : void
	********************************************************/
	private void initTextFields(String name, Float servingSize, Float calories)
	{
		nameField = new JTextField(name);
		nameField.setMinimumSize(new Dimension(200,25));
		
		numServingsField = new JTextField(Float.toString(servingSize));
		numServingsField.setMinimumSize(new Dimension(30,25));
		
		caloriesField = new JTextField(Float.toString(calories));
		caloriesField.setMinimumSize(new Dimension(200,25));
	}
	
	/********************************************************
	* Name       : initTextArea
	* Purpose    : Initialize areas
	* Parameters : String instructions
	* Returns    : void
	********************************************************/
	private void initTextArea(String instructions)
	{
		instructionsArea = new JTextArea(instructions);
		instructionsArea.setLineWrap(true);
		instructionsArea.setWrapStyleWord(true);
		instructionScroll = new JScrollPane();
		instructionScroll.setMinimumSize(new Dimension(350,400));
		instructionScroll.setMaximumSize(new Dimension(350,400));
		instructionScroll.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
		instructionScroll.setViewportView(instructionsArea);
		
	}
	
	/********************************************************
	* Name       : initButtons
	* Purpose    : Initialize buttons
	* Returns    : void
	********************************************************/
	private void initButtons()
	{
		
		plusIngField = new JButton("+");
		plusIngField.addActionListener(this);
		plusIngField.setMnemonic(KeyEvent.VK_EQUALS);
		
		
		minusIngField = new JButton("-");
		minusIngField.addActionListener(this);
		minusIngField.setMnemonic(KeyEvent.VK_MINUS);
		
		saveButton = new JButton("Save Recipe");
		saveButton.setBackground(Color.GREEN);
		saveButton.setMinimumSize(new Dimension(BUTTON_WIDTH, BUTTON_HEIGHT));
		saveButton.setMaximumSize(new Dimension(BUTTON_WIDTH, BUTTON_HEIGHT));
		saveButton.addActionListener(this);
		
		cancelButton = new JButton("Cancel");
		cancelButton.setMinimumSize(new Dimension(BUTTON_WIDTH, BUTTON_HEIGHT));
		cancelButton.setMaximumSize(new Dimension(BUTTON_WIDTH, BUTTON_HEIGHT));
		cancelButton.addActionListener(this);
		
		printButton = new JButton("Print Recipe");
		printButton.setBackground(Color.CYAN);
		printButton.setMinimumSize(new Dimension(BUTTON_WIDTH, BUTTON_HEIGHT));
		printButton.setMaximumSize(new Dimension(BUTTON_WIDTH, BUTTON_HEIGHT));
		printButton.addActionListener(this);
		
		deleteButton = new JButton("Delete Recipe");
		deleteButton.setBackground(Color.RED);
		deleteButton.setMinimumSize(new Dimension(BUTTON_WIDTH, BUTTON_HEIGHT));
		deleteButton.setMaximumSize(new Dimension(BUTTON_WIDTH, BUTTON_HEIGHT));
		deleteButton.addActionListener(this);
		

	}
	
	/********************************************************
	* Name       : initCheckBox
	* Purpose    : Initialize check box
	* Returns    : void
	********************************************************/
	private void initBoxs(int catergoryID, boolean favorite)
	{
		favoriteCheckBox = new JCheckBox("Favorite");
		favoriteCheckBox.setSelected(favorite);
		HashMap<Integer, String> tempMap = cookbook.getCategoryHashMap();
		String[] comboBoxArray = new String[tempMap.size()];
		comboBoxArray = tempMap.values().toArray(comboBoxArray);
		categoryCombo = new JComboBox<>(comboBoxArray);
		categoryCombo.setMinimumSize(new Dimension(200,25));
		categoryCombo.setToolTipText("Choose a category");
		categoryCombo.setSelectedIndex(catergoryID);
		
	}
	
	/********************************************************
	* Name       : initPanel
	* Purpose    : Initialize the panels
	* Returns    : void
	********************************************************/
	private void initPanel()
	{
		ingredientPanel = new IngredientPanel(ingredients);
		if(ingredients.size() < 1)
		{
			ingredientPanel.addNewIngredientField("", (float) 0, Measurement.CUP);
		}
		
		ingredientScroll = new JScrollPane();
		ingredientScroll.setMinimumSize(new Dimension(350,400));
		ingredientScroll.setMaximumSize(new Dimension(350,400));
		ingredientScroll.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
		
		ingredientScroll.setViewportView(ingredientPanel);
		
		
	}
	
	/********************************************************
	* Name       : initImage
	* Purpose    : 
	* Parameters : String path
	* Returns    : void
	********************************************************/
	private void initImage(String path)
	{	
		picturePanel = new ImagePanel(recipe.getPicture());
		picturePanel.setMaximumSize(new Dimension(300,300));
		picturePanel.addMouseListener(this);
	}

	/********************************************************
	* Name       : addComponents
	* Purpose    : Add components to the panel
	* Returns    : void
	********************************************************/
	private void addComponents()
	{
		add(nameLabel, "cell 0 0");
		add(nameField, "cell 0 0");
		
		add(saveButton, "cell 1 0");
		add(printButton, "cell 1 0");
		add(deleteButton, "cell 1 0");
		add(cancelButton, "cell 1 0");
		
		
		add(numServingsLabel,"cell 0 1");
		add(numServingsField,"cell 0 1");
		add(categoryCombo, "cell 0 1");
		
		add(favoriteCheckBox, "cell 1 1");
		add(calorieLabel, "cell 1 1");
		add(caloriesField, "cell 1 1");
		
		add(plusIngField, "cell 0 2");
		add(minusIngField, "cell 0 2");
		add(ingredientsLabel, "cell 0 2");
		add(ingredientScroll, "cell 0 3 2 2");		
		
		add(picturePanel, "cell 1 3");
		add(pictureLabel, "cell 1 4");
		
		add(instructionsLabel, "cell 0 5");
		add(instructionScroll, "cell 0 6");
		
		
				
	}	
	
	@Override
	public String getName()
	{
		return nameField.getText();
	}

	/********************************************************
	* Name       : checkRequiredFields
	* Purpose    : 
	* Parameters : 
	* Returns    : void
	********************************************************/
	private Boolean checkRequiredFields()
	{
		boolean nameBool = false, ingredientNameBool = false, 
				instructionBool = false;
		
		if(nameField.getText() == null)
		{
			nameBool = false;					
		}
		else
		{
			nameBool = true;
		}
		if(nameField.getText().equals(""))
		{
			nameBool = false;
		}
		else
		{
			nameBool = true;
		}
		
		if(instructionsArea.getText().equals(""))
		{
			instructionBool = false;
		}
		else
		{
			instructionBool = true;
		}
		
		try
		{
			ingredientPanel.saveIngredients();
		}
		catch (Exception e)
		{
			
		}
		for(int i = 0; i < ingredients.size(); i++)
		{
			if(ingredients.get(i).getName().equals(""))
			{
				ingredientNameBool = false;
				break;
			}
			else
				ingredientNameBool = true;
			
			if(ingredients.get(i).getName().equals("default name"))
			{
				ingredientNameBool = false;
				break;
			}
			else
				ingredientNameBool = true;
		}
	
		
		
		if(ingredientNameBool && instructionBool && nameBool)
		{
			return true;
		}
		else
		{
			String check = "One of the required fields is empty.\nPlease check:\n";
			if(!nameBool)
			{
				check += "Recipe Name\n";
			}
			if(!ingredientNameBool)
			{
				check += "Ingredient Names\n";
			}
			if(!instructionBool)
			{
				check += "Instructions\n";
			}
			
			
			JOptionPane.showMessageDialog(this, check);
			return false;
		}
		
	}
	
	/**
	 * @return the recipe
	 */
	public Recipe getRecipe()
	{
		recipe = new Recipe(nameField.getText(), ingredients, instructionsArea.getText(), 
				Float.parseFloat(caloriesField.getText()), Float.parseFloat(numServingsField.getText()), 
				recipe.getPicture(), favoriteCheckBox.isSelected(), categoryCombo.getSelectedIndex(), cookbook.pullCategory(categoryCombo.getSelectedIndex()));
		return recipe;
	}

	/**
	 * Action Listener
	 */
	@Override
	public void actionPerformed(ActionEvent e)
	{
		if(e.getSource() == plusIngField)
		{
			ingredientPanel.addNewIngredientField("", (float) 0, Measurement.CUP);
			ingredientScroll.revalidate();
			validate();
		}
		
		if(e.getSource() == minusIngField)
		{
			ingredientPanel.removeIngredientField();
			ingredientScroll.setViewportView(ingredientPanel);
			ingredientScroll.revalidate();
			validate();
			
		}
		
		if(e.getSource() == saveButton)
		{
			if(checkRequiredFields())
			{
				if(recipe.getRe_uniqueID() == -1)
				{
					
					try
					{
						ingredientPanel.saveIngredients();
						Float.parseFloat(caloriesField.getText());
						recipe = new Recipe(nameField.getText(), ingredients, instructionsArea.getText(), 
								Float.parseFloat(caloriesField.getText()), Float.parseFloat(numServingsField.getText()), 
								recipe.getPicture(), favoriteCheckBox.isSelected(), categoryCombo.getSelectedIndex(), cookbook.pullCategory(categoryCombo.getSelectedIndex()));
						int newRecipeID = cookbook.addRecipeToDB(recipe);
						recipe.setRe_uniqueID(newRecipeID);
						JOptionPane.showMessageDialog(this.getParent(), "Recipe Saved");
					}
					catch (Exception e2)
					{
						JOptionPane.showMessageDialog(this.getParent(), "Calorie and Ingredient Amount fields\n must be numbers only like 1.0 or 1.", "", JOptionPane.ERROR_MESSAGE);
					}
							
				}
				else
				{
					try
					{
						Float.parseFloat(caloriesField.getText());
						Object[] options = {"Yes","No","Cancel"};
						int overWrite = JOptionPane.showOptionDialog(this.getParent(), "This recipe already exists would you like to overwrite it?", "Overwrite recipe", 
								JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE, null, options, options[2]);
						if (overWrite == 0)
						{
							ingredientPanel.saveIngredients();
							recipe = new Recipe(recipe.getRe_uniqueID(),nameField.getText(), ingredients, instructionsArea.getText(), 
									Float.parseFloat(caloriesField.getText()), Float.parseFloat(numServingsField.getText()), 
									recipe.getPicture(), favoriteCheckBox.isSelected(), categoryCombo.getSelectedIndex(), cookbook.pullCategory(categoryCombo.getSelectedIndex()));
							cookbook.updateRecipeInDB(recipe);
							JOptionPane.showMessageDialog(this.getParent(), "Recipe Saved");
						}	
					}
					catch (Exception e2)
					{
						JOptionPane.showMessageDialog(this.getParent(), "Calorie and Ingredient Amount fields\n must be numbers only like 1.0 or 1.", "", JOptionPane.ERROR_MESSAGE);
					}
					
				}
			}
			
			
		}
		
		if(e.getSource() == printButton)
		{
			
			PrinterJob job = PrinterJob.getPrinterJob();
			job.setPrintable(new PrintRecipePanel(recipe));
			boolean ok = job.printDialog();
			if(ok)
			{
				try
				{
					job.print();
				}
				catch (PrinterException e1)
				{
					e1.printStackTrace();
				}
			}
			
		}
		
		if(e.getSource() == deleteButton)
		{
			if(recipe.getRe_uniqueID() != -1)
			{
				Object[] delOptions = {"Yes","No","Cancel"};
				int delete = JOptionPane.showOptionDialog(this.getParent(), "Delete this recipe?", "Delete recipe", 
						JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE, null, delOptions, delOptions[2]);
				if (delete == 0)
				{
					cookbook.deleteRecipeInDB(recipe.getRe_uniqueID());
					int index = Gui.tabbedPane.getSelectedIndex();
					JOptionPane.showMessageDialog(this.getParent(), "Recipe Deleted.");
					Gui.homePanel.refreshLists();
					Gui.tabbedPane.setSelectedIndex(0);
					Gui.tabbedPane.remove(index);
				}
					
			}
			else
				JOptionPane.showMessageDialog(this.getParent(), "This recipe does not exist yet.");

				
			
		}
		
		if(e.getSource() == cancelButton)
		{
			Object[] options = {"Yes","No"};
			int cancel = JOptionPane.showOptionDialog(this.getParent(), "Any unsaved changes will be lost are you sure?", "Cancel", 
					JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE, null, options, options[1]);
			if(cancel == 0)
			{
				int index = Gui.tabbedPane.getSelectedIndex();
				if(!(recipe.getRe_uniqueID() == -1))
				{
					JScrollPane tabScroll = (JScrollPane) Gui.tabbedPane.getComponentAt(index);
					tabScroll.setViewportView(new RecipePanel(recipe));
				}
				else
				{
					Gui.homePanel.refreshLists();
					Gui.tabbedPane.setSelectedIndex(0);
					Gui.tabbedPane.remove(index);
				}
				
				
			}
			
		}
				
	}

	/**
	 * Mouse Listener
	 */
	@Override
	public void mouseClicked(MouseEvent e)
	{
		if(e.getClickCount() == 2)
		{
			if(e.getSource() == picturePanel)
			{
				Object[] options = {"Update","Remove","Cancel"};
				int update = JOptionPane.showOptionDialog(this.getParent(), "Would you like to update or remove this photo?", "Update Photo", 
						JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE, null, options, options[2]);
				
				if(update == 0)
				{
					int returnValue = fileChooser.showOpenDialog(this.getParent());
					if(returnValue == JFileChooser.APPROVE_OPTION)
					{
						recipe.setPicture(fileChooser.getSelectedFile().getAbsolutePath());
						picturePanel.setImagePath(fileChooser.getSelectedFile().getAbsolutePath());
						picturePanel.revalidate();
						validate();
					}
				}
				if(update == 1)
				{
					recipe.setPicture("/resources/recipes.png");
					picturePanel.setImagePath("/resources/recipes.png");
					picturePanel.revalidate();
					validate();
				}
				
				
			}
		}
		
	}



	/* (non-Javadoc)
	 * @see java.awt.event.MouseListener#mouseEntered(java.awt.event.MouseEvent)
	 */
	@Override
	public void mouseEntered(MouseEvent e)
	{
		// TODO Auto-generated method stub
		
	}



	/* (non-Javadoc)
	 * @see java.awt.event.MouseListener#mouseExited(java.awt.event.MouseEvent)
	 */
	@Override
	public void mouseExited(MouseEvent e)
	{
		// TODO Auto-generated method stub
		
	}



	/* (non-Javadoc)
	 * @see java.awt.event.MouseListener#mousePressed(java.awt.event.MouseEvent)
	 */
	@Override
	public void mousePressed(MouseEvent e)
	{
		// TODO Auto-generated method stub
		
	}



	/* (non-Javadoc)
	 * @see java.awt.event.MouseListener#mouseReleased(java.awt.event.MouseEvent)
	 */
	@Override
	public void mouseReleased(MouseEvent e)
	{
		// TODO Auto-generated method stub
		
	}

}
